#pragma once
#include <pthread.h>
#include <vector>
#include <unistd.h>
#include "thread.hpp"
#include "task.hpp"
#include "ProConModel.hpp"
#include "doubleBuf.hpp"

// 单例模式 - 懒汉模式
template <typename T>
class ThreadPool
{
public:
    using excuteCB = std::function<void(T &)>; // 处理任务的回调
    using getCB = std::function<void(T *)>;    // 获取任务的回调
    // typename basic_buf<Task>::ptr _buf;
    // excuteCB _exc;
    // getCB _get;
    //  int _num;
    ThreadPool(typename basic_buf<Task>::ptr buf,excuteCB exc,getCB get,int num)
    :_buf(buf)
    ,_exc(exc)
    ,_get(get)
    ,_num(num)
    {

    }

    static ThreadPool *GetInstance(excuteCB cb,getCB get,int num = 1)
    {
        // 双条件判断，频繁申请释放锁
        if (_instance == nullptr)
        {
            // _mt防止刚开始多线程进入，同时进行初始化
            pthread_mutex_lock(&_mt);
            if (_instance == nullptr)
            {
                _instance = new ThreadPool<T>(std::make_shared<DoubleBuf<T>>(),cb,get,num);
                    _instance->init();
                    _instance->start();
            }
            pthread_mutex_unlock(&_mt);
        }
        return _instance;
    }
    // // 另一种懒汉模式， 依靠c++11的特性 static
    // // 在c++11中，static是线程安全的
    // static ThreadPool &GetInstance()
    // {
    //     static ThreadPool instance;
    //     return instance;
    // }
    void init()
    {
        for (int i = 0; i < _num; i++)
        {
            std::string name = "线程-" + std::to_string(i);
            _ths.emplace_back(std::bind(&ThreadPool::consumer,this),name,nullptr);
        }
    }
    void start()
    {
        for (int i = 0; i < _num; i++)
        {
            _ths[i].create();
        }
    }

    // 也是可以直接复用ProConModel类的
    // 只需要线程的的回调函数设置为 pc::consumer
    // 线程池中producer::使用pc::producer


    // 线程需要执行的函数
    // 不断从任务队列中获取任务，执行任务
    void consumer()
    {
        while (true)
        {
            // cout << "我是消费者，我开始获取任务了" << endl;
            T t;
            _buf->pop(&t);
            cout << "threadPool::consumer" << endl;
            cout << "我从任务队列中获取到了任务" << endl;
            _exc(t);
            cout << "任务处理结束" << endl;
        }
    }
    // 生产者：用户产生任务，线程池获取任务，并塞入到任务队列中
    void producer()
    {
        while(true)
        {
            T t;
            _get(&t);
            // _buf.push(t);
            _buf->push(t);
            cout << "threadPool::producer" << endl;
            cout << "我生产了一个任务,并放入缓冲区中了" << endl;
        }
    }
    
    void PushTask(T& t)
    {
        _buf->push(t);
        cout << "threadPool::producer" << endl;
        cout << "我生产了一个任务,并放入缓冲区中了" << endl;
    }
    ~ThreadPool()
    {
        if(_ths[0].getType() == Thread::MODE::JOIN)
        {
            for(auto& ts : _ths)
                ts.join();
        }
    }
private:
    ThreadPool()
    {
    }
    // 两种方法 删除拷贝构造，和赋值重载
    ThreadPool(const ThreadPool<T> &tp) = delete;

    ThreadPool<T> &operator=(const ThreadPool<T> &tp) = delete;

private:
    static pthread_mutex_t _mt;
    static ThreadPool *_instance;

private:
    std::vector<Thread> _ths;
    typename basic_buf<T>::ptr _buf;
    excuteCB _exc;
    getCB _get;
     int _num;
};
template <typename T>
pthread_mutex_t ThreadPool<T>::_mt = PTHREAD_MUTEX_INITIALIZER;

template <typename T>
ThreadPool<T> *ThreadPool<T>::_instance = nullptr;
